home *** CD-ROM | disk | FTP | other *** search
- /* File: anytoucd.c:
- Author: Charlie Gunn originally
-
- read a OOGL object on stdin, and write ucd format on stdout.
- */
- #include "vec4.h"
- #include "geom.h"
- #include "3d.h"
- #include "polylistP.h"
- #include "plutil.h"
- #include <stdio.h>
- #include "time.h"
-
- extern Poly *getstack(); /* in stack.c */
-
-
- #define MAXV 64
-
- /*
- #define DEBUG
- */
-
- #define CAVE 1
- #define VEX 0
- static int debug = 0;
-
- #define INSIDE(line, point) \
- ((line.a*(point)->x + line.b*(point)->y + line.c) <= 0)
- #define INSIDE2(line, point) \
- (line.a*(point)->x + line.b*(point)->y + line.c)
-
- struct polygon {
- int nv;
- unsigned int new:1;
- Vertex *vlist[MAXV];
- HPoint3 vlistxy[MAXV];
- short inout[MAXV];
- Transform to_xy;
- } currpoly;
-
- struct line {
- float a,b,c,angle;
- };
-
- typedef struct polygon polygon;
- typedef struct line line;
-
- void
- myconvert(CP, cp)
- Poly *CP;
- polygon *cp;
- {
- int i;
- cp->nv = CP->n_vertices;
- for (i=0; i<cp->nv; ++i)
- cp->vlist[i] = CP->v[i];
- cp->new = 1;
- }
-
- polygon *
- chopup (pp, PP)
- polygon *pp;
- Poly *PP;
- {
- int oc, nc, n, i ;
- int cutcount = 0, convex, orient;
- line edges[MAXV];
- Transform m;
- double tt, dangle, sum;
- polygon *newpoly;
-
- if (debug){
- fprintf(stderr,"Entering chopup with %d vertices \n",pp->nv);
- for (i=0; i<pp->nv; ++i)
- fprintf(stderr,"%f %f %f \n",pp->vlist[i]->pt.x, pp->vlist[i]->pt.y, pp->vlist[i]->pt.z);
- }
-
- if (pp->nv <= 4 && pp->nv > 1)
- {
- PP->n_vertices = pp->nv;
- for (i=0; i<pp->nv; ++i)
- PP->v[i] = pp->vlist[i];
- if (push(PP) == 0)
- OOGLError(1,"anytoucd: unable to push polygon\n");
- return(NULL);
- }
- else if (pp->nv == 1)
- {
- return(NULL);
- }
-
- else { /* something to chop */
-
- newpoly = OOGLNew(polygon);
- n = pp->nv;
- if (pp->new)
- {
- /* need to work in the x,y plane, so compute approp. tforms */
- for (i=0; i<n; ++i) /* may need to hunt for independent vectors */
- if (make_tform(&pp->vlist[i]->pt, &pp->vlist[(i+1)%n]->pt, &pp->vlist[(i+2)%n]->pt, pp->to_xy) >= 0) break;;
- TmInvert(pp->to_xy, pp->to_xy);
-
- for (i=0; i<pp->nv; ++i)
- HPt3Transform(pp->to_xy, &pp->vlist[i]->pt, &pp->vlistxy[i]);
- pp->new = 0;
- }
-
-
- {
- double dx, dy;
- for (i=0; i<pp->nv; ++i)
- {
- dx = pp->vlistxy[(i+1)%n].x - pp->vlistxy[i].x;
- dy = pp->vlistxy[(i+1)%n].y - pp->vlistxy[i].y;
- edges[i].a = dy;
- edges[i].b = -dx;
- edges[i].c = -(edges[i].a*pp->vlistxy[i].x+edges[i].b*pp->vlistxy[i].y);
- edges[i].angle = atan2(dy,dx);
- if (debug)
- fprintf(stderr,"edge %d: angle %f\n",i,edges[i].angle);
- }
- }
-
- /* armed with this info, identify concave and convex bndy pts*/
- for (sum = 0.0, i=0; i<pp->nv; ++i)
- {
- dangle = edges[i].angle - edges[(i-1+n)%n].angle ;
- /* clip to (-PI, +PI) */
- while (dangle < -PI) dangle += 2*PI;
- while (dangle > PI) dangle -= 2*PI;
- sum += dangle;
- if (dangle > 0) pp->inout[i] = VEX;
- else pp->inout[i] = CAVE;
- }
-
- if (debug)
- fprintf(stderr,"Total angle change is %f\n",sum);
- if (sum > 0 ) orient = 1;
- else orient = -1;
- for (convex = 1, i=0; i<pp->nv; ++i)
- {
- if (orient == -1)
- {
- pp->inout[i] = 1 - pp->inout[i];
- edges[i].a *= -1;
- edges[i].b *= -1;
- edges[i].c *= -1;
- }
- if (pp->inout[i] == CAVE) convex = 0;
- }
-
- if (debug)
- if (convex) fprintf(stderr,"Polygon is convex\n");
-
- /* next look for triangles to chop off */
- {
- line cutcorner;
- double a,b,c,angle, dx, dy;
- int cutoff, j, jj,ni, pi, oc, nc;
- double d0, d1, d2;
-
- for (nc = 0, oc=0; oc<pp->nv-1; ++oc, ++nc)
- {
- /* copy out current vertex */
- newpoly->vlist[nc] = pp->vlist[oc];
- HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]);
- if (pp->inout[(oc+1)%n] == VEX)
- {
- cutoff = 1; /* default is to cut if off */
- if (!convex)
- {
- pi = oc;
- ni = (oc+2)%n;
- dx = pp->vlistxy[(oc+2)%n].x - pp->vlistxy[oc].x;
- dy = pp->vlistxy[(oc+2)%n].y - pp->vlistxy[oc].y;
- /* orient this line to run from v2 to v0, to agree with edges */
- cutcorner.a = -dy*orient;
- cutcorner.b = dx*orient;
- cutcorner.c = -(cutcorner.a*pp->vlistxy[(oc+2)%n].x+cutcorner.b*pp->vlistxy[(oc+2)%n].y);
- cutcorner.angle = -atan2(dy,dx);
- /* check for concave pts inside this triangle */
- /* don't check the vertices of this triangle */
- for ( j=0, jj=oc+3; j<pp->nv-3 && cutoff; ++j,++jj)
- {
- if (jj == pp->nv) jj = 0;
- if ( pp->inout[jj] == CAVE )
- {
- if (INSIDE(cutcorner,&pp->vlistxy[jj]) &&
- INSIDE(edges[oc], &pp->vlistxy[jj]) &&
- INSIDE(edges[(oc+1)%n], &pp->vlistxy[jj]))
- {
- if (debug)
- fprintf(stderr,"vertex %d is inside cutoff corner %d %d %d\n",jj, oc, oc+1, oc+2);
- cutoff = 0;
- }
- }
- }
- }
- if (cutoff) /* can cut this corner off */
- {
- int iv0, iv1, iv2, iv3;
- if (convex & (oc < pp->nv-2 ) )
- /* can cut off 4 vertices */
- {
- iv0 = oc;
- iv1 = (oc+1)%n;
- iv2 = (oc+2)%n;
- iv3 = (oc+3)%n;
- PP->n_vertices = 4;
- PP->v[0] = pp->vlist[iv0];
- PP->v[1] = pp->vlist[iv1];
- PP->v[2] = pp->vlist[iv2];
- PP->v[3] = pp->vlist[iv3];
- if (push(PP) == 0)
- OOGLError(1,"anytoucd: unable to push polygon\n");
- oc++;
- oc++;
- }
- else
- {
- iv0 = oc;
- iv1 = (oc+1)%n;
- iv2 = (oc+2)%n;
- PP->n_vertices = 3;
- PP->v[0] = pp->vlist[iv0];
- PP->v[1] = pp->vlist[iv1];
- PP->v[2] = pp->vlist[iv2];
- if (push(PP) == 0)
- OOGLError(1,"anytoucd: unable to push polygon\n");
- oc++;
- }
-
- }
- }
- }
- while (oc < pp->nv)
- {
- newpoly->vlist[nc] = pp->vlist[oc];
- HPt3Copy(&pp->vlistxy[oc], &newpoly->vlistxy[nc]);
- oc++;
- nc++;
- }
- newpoly->new = 0;
- newpoly->nv = nc;
-
- /* if nothing got chopped, or if what's left
- * has only 1 or 2 vertices */
- if (newpoly->nv == pp->nv || newpoly->nv <= 2)
- {
- /*
- fprintf(stderr,"chopup:Unable to cut a corner\n");
- */
- OOGLFree(newpoly);
- return(NULL);
- }
-
- else return(newpoly);
- }
- }
- }
-
- Poly *CP, thisPoly;
-
- main(argc, argv) int argc; char **argv;
- {
- register polygon *ncp, *cp, thispolygon;
- int i, nv, pcountold, pcountnew;
- char type[64];
- HPoint3 vd;
- Geom *thisgeom;
- PolyList *thispl, *newpl;
- Vertex *vlist[4];
- Transform id;
-
- TmIdentity(id);
- thisgeom = GeomFLoad(stdin,NULL);
- thispl = (PolyList*)AnyToPL(thisgeom, id);
- newpl = (PolyList*)GeomCopy((Geom*)thispl);
- if (initstack() == 0)
- OOGLError(1,"anytoucd: unable to init stack\n");
-
- cp = OOGLNew(polygon);
- CP = &thisPoly;
- /* at most 4 vertices in each face */
- for (pcountold = 0; pcountold < thispl->n_polys; ++pcountold)
- {
- myconvert(&thispl->p[pcountold], cp);
- bcopy(&thispl->p[pcountold], CP, sizeof(Poly));
- CP->v = vlist;
- OOGLNew(polygon);
- while ( (ncp = chopup(cp, CP)) != NULL )
- {
- if (debug)
- fprintf(stderr,"Chop up: calling again\n");
-
- OOGLFree(cp);
- cp = ncp;
- }
- }
- /* now get the list of polygons from the stack */
- thispl->n_polys = getsize();
- thispl->p = getstack();
-
- /* now print out the stuff in ucd format */
- /* GeomFSave(thispl, stdout, NULL); */
- {
- FILE *fp = stdout;
- int num_nodes,
- num_node_data_comp = 0,
- node_data_comp[2],
- num_cells,
- num_cell_data_comp = 0,
- total_node_comp = 0,
- total_cell_comp = 0,
- cell_data_comp[2],
- i,j,n;
- Poly *p;
- Vertex *v, **vp;
-
- num_nodes = thispl->n_verts;
- num_cells = thispl->n_polys;
- if (thispl->flags & PL_HASVCOL) {
- node_data_comp[0] = 4; /* ColorA's : 4 component */
- num_node_data_comp += 1;
- total_node_comp += 4;
- }
- if (thispl->flags & PL_HASVN) {
- node_data_comp[num_node_data_comp] = 3;
- num_node_data_comp += 1;
- total_node_comp += 3;
- }
- #ifdef FOURD
- if (thispl->geomflags & VERT_4D) {
- node_data_comp[num_node_data_comp] = 1; /* ColorA's : 4 component */
- num_node_data_comp += 1;
- total_node_comp += 1;
- }
- #endif
- if (thispl->flags & PL_HASPCOL) {
- cell_data_comp[0] = 4; /* ColorA's : 4 component */
- num_cell_data_comp += 1;
- total_cell_comp += 4;
- }
- if (thispl->flags & PL_HASPN) {
- cell_data_comp[num_cell_data_comp] = 3;
- num_cell_data_comp += 1;
- total_cell_comp += 3;
- }
- {
- char *timestring;
- long mytime;
- time_t myt;
- myt = time(&mytime);
- timestring = ctime(&myt);
- fprintf(fp,"# Created by anytoucd on %s \n",timestring);
- }
-
- fprintf(fp,"%d %d %d %d 0\n",num_nodes, num_cells, total_node_comp, total_cell_comp);
- /* write out vertices */
- /* what to do about 4D vertices? */
- for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
- #ifdef FOURD
- fprintf(fp,"%d %g %g %g\n",i+1,v->pt.x, v->pt.y, v->pt.z);
- #else
- {
- float w = v->pt.w;
- if (w) w = 1.0/w;
- fprintf(fp,"%d %g %g %g\n",i+1,w*v->pt.x, w*v->pt.y, w*v->pt.z);
- }
- #endif
-
-
- /* write out faces */
- for (i=0, p = thispl->p; i<thispl->n_polys; ++i, ++p) {
- fprintf(fp,"%d 1 ",i+1);
- n = p->n_vertices;
- if (n==2) fprintf(fp,"line "); /* is this right? */
- else if (n==3) fprintf(fp,"tri ");
- else if (n==4) fprintf(fp, "quad ");
- /* else signal error */
- else return;
- for(vp = p->v; --n >= 0; vp++)
- fprintf(fp, "%d ", (*vp) - thispl->vl + 1);
- fprintf(fp,"\n");
- }
-
- if (num_node_data_comp) {
- fprintf(fp,"%d ", num_node_data_comp);
- for (i=0; i<num_node_data_comp; ++i)
- fprintf(fp,"%d ", node_data_comp[i]);
- fprintf(fp,"\n");
- }
-
- if (thispl->flags & PL_HASVCOL) fprintf(fp,"rgba, NULL\n");
- if (thispl->flags & PL_HASVN) fprintf(fp,"normal, NULL\n");
- if (thispl->geomflags & VERT_4D) fprintf(fp,"w, NULL\n");
-
- /* print vertex colors */
- if (thispl->flags & PL_HASVCOL) {
- for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
- fprintf(fp,"%d %g %g %g %g\n", i+1, v->vcol.r, v->vcol.g, v->vcol.b, v->vcol.a);
- }
-
- /* print vertex normals */
- if (thispl->flags & PL_HASVN) {
- for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
- fprintf(fp,"%d %g %g %g\n", i+1, v->vn.x, v->vn.y, v->vn.z);
- }
-
- #ifdef FOURD
- /* print fourth coordinate if present */
- if (thispl->geomflags & VERT_4D) {
- for (v = thispl->vl, i=0; i<thispl->n_verts; ++i, ++v)
- fprintf(fp,"%d %g\n", i+1, v->pt.w);
- }
- #endif
-
- /* now process cell data */
- if (num_cell_data_comp) {
- fprintf(fp,"%d ", num_cell_data_comp);
- for (i=0; i<num_cell_data_comp; ++i)
- fprintf(fp,"%d ", cell_data_comp[i]);
- fprintf(fp,"\n");
- }
- /* print labels */
- if (thispl->flags & PL_HASPCOL) fprintf(fp,"rgba, NULL\n");
- if (thispl->flags & PL_HASPN) fprintf(fp,"normal, NULL\n");
-
- /* print face colors */
- if (thispl->flags & PL_HASPCOL) {
- for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p)
- fprintf(fp,"%d %g %g %g %g\n", i+1, p->pcol.r, p->pcol.g, p->pcol.b, p->pcol.a);
- }
-
- /* print face normals */
- if (thispl->flags & PL_HASPN) {
- for (p = thispl->p, i=0; i<thispl->n_polys; ++i, ++p)
- fprintf(fp,"%d %g %g %g\n", i+1, p->pn.x, p->pn.y, p->pn.z);
- }
- }
- }
-
-
-